/******************************************************************************* * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.ui.internal; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import org.eclipse.core.runtime.Assert; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IMemento; import org.eclipse.ui.INavigationHistory; import org.eclipse.ui.INavigationLocation; import org.eclipse.ui.INavigationLocationProvider; import org.eclipse.ui.IPartListener2; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.internal.StartupThreading.StartupRunnable; /** * Implementation of the back and forward actions. */ public class NavigationHistory implements INavigationHistory { private static final boolean DEBUG= false; private static final int CAPACITY = 50; private NavigationHistoryAction backwardAction; private NavigationHistoryAction forwardAction; private int ignoreEntries; private ArrayList history = new ArrayList(CAPACITY); Map perTabHistoryMap = new HashMap(); private ArrayList editors = new ArrayList(CAPACITY); private IWorkbenchPage page; private int activeEntry = 0; /** * Creates a new NavigationHistory to keep the NavigationLocation entries of the specified page. * * @param page the workbench page */ public NavigationHistory(final IWorkbenchPage page) { this.page = page; page.addPartListener(new IPartListener2() { @Override public void partActivated(IWorkbenchPartReference partRef) { } @Override public void partBroughtToTop(IWorkbenchPartReference partRef) { } @Override public void partDeactivated(IWorkbenchPartReference partRef) { } @Override public void partOpened(IWorkbenchPartReference partRef) { } @Override public void partHidden(IWorkbenchPartReference partRef) { } @Override public void partVisible(IWorkbenchPartReference partRef) { } @Override public void partClosed(IWorkbenchPartReference partRef) { if (isPerTabHistoryEnabled() && partRef instanceof EditorReference) { if (!((EditorReference)partRef).isDisposed()) { Object editorTabCookie = ((EditorReference) partRef).getModel().getWidget(); disposeHistoryForTab(editorTabCookie); updateActions(); } } updateNavigationHistory(partRef, true); } @Override public void partInputChanged(IWorkbenchPartReference partRef) { updateNavigationHistory(partRef, false); } private void updateNavigationHistory(IWorkbenchPartReference partRef, boolean partClosed) { if (partRef != null && partRef.getPart(false) instanceof IEditorPart) { IEditorPart editor = (IEditorPart) partRef.getPart(false); IEditorInput input = editor.getEditorInput(); String id = editor.getSite().getId(); Iterator e = editors.iterator(); NavigationHistoryEditorInfo info = null; NavigationHistoryEditorInfo currentInfo = null; NavigationHistoryEntry current = getEntry(activeEntry); if (current != null) { currentInfo = current.editorInfo; } while (e.hasNext()) { info = (NavigationHistoryEditorInfo) e.next(); if (id.equals(info.editorID) && input.equals(info.editorInput)) { if (partClosed && info != currentInfo) { info.handlePartClosed(); } break; } info = null; } if (info == null) { return; } boolean isEntryDisposed = false; e = history.iterator(); int i = 0; while (e.hasNext()) { NavigationHistoryEntry entry = (NavigationHistoryEntry) e .next(); if (entry.editorInfo == info) { if (!entry.handlePartClosed()) { // update the active entry since we are removing an item if (i < activeEntry) { activeEntry--; } else if (i == activeEntry) { if (i != 0) { activeEntry--; } } else { // activeEntry is before item we deleted i++; } isEntryDisposed = true; e.remove(); disposeEntry(entry); } else { i++; } } } /* * Promote the entry of the last closed editor to be the active * one, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=154431 */ if (!isEntryDisposed && page.getActiveEditor() == null && activeEntry < history.size()) activeEntry++; updateActions(); } } }); } private Display getDisplay() { return page.getWorkbenchWindow().getShell().getDisplay(); } private boolean isPerTabHistoryEnabled() { return false; } /* * Adds an editor to the editor history without getting its location. */ public void markEditor(final IEditorPart part) { if (ignoreEntries > 0 || part == null) { return; } /* Ignore all entries until the async exec runs. Workaround to avoid * extra entry when using Open Declaration (F3) that opens another editor. */ ignoreEntries++; getDisplay().asyncExec(() -> { if (--ignoreEntries == 0) { if (part.getEditorSite() instanceof EditorSite) { EditorSite site = (EditorSite) part.getEditorSite(); Control c = (Control) site.getModel().getWidget(); if (c == null || c.isDisposed()) { return; } NavigationHistoryEntry e = getEntry(activeEntry); if (e != null && part.getEditorInput() != e.editorInfo.editorInput) { updateEntry(e); } addEntry(part); } } }); } @Override public void markLocation(IEditorPart part) { addEntry(part); } /* * Return the backward history entries. Return in restore order (i.e., the * first entry is the entry that would become active if the "Backward" action * was executed). * <p> * (Called by NavigationHistoryAction) * </p> */ NavigationHistoryEntry[] getBackwardEntries() { if (isPerTabHistoryEnabled()) { return getEntriesForTab(false); } int length = activeEntry; NavigationHistoryEntry[] entries = new NavigationHistoryEntry[length]; for (int i = 0; i < activeEntry; i++) { entries[activeEntry - 1 - i] = getEntry(i); } return entries; } /* * Return the forward history entries. Return in restore order (i.e., the first * entry is the entry that would become active if the "Forward" action was * executed). * <p> * (Called by NavigationHistoryAction) * </p> */ NavigationHistoryEntry[] getForwardEntries() { if (isPerTabHistoryEnabled()) { return getEntriesForTab(true); } int length = history.size() - activeEntry - 1; length = Math.max(0, length); NavigationHistoryEntry[] entries = new NavigationHistoryEntry[length]; for (int i = activeEntry + 1; i < history.size(); i++) { entries[i - activeEntry - 1] = getEntry(i); } return entries; } @Override public INavigationLocation[] getLocations() { INavigationLocation result[] = new INavigationLocation[history.size()]; for (int i = 0; i < result.length; i++) { NavigationHistoryEntry e = (NavigationHistoryEntry) history.get(i); result[i] = e.location; } return result; } @Override public INavigationLocation getCurrentLocation() { NavigationHistoryEntry entry = getEntry(activeEntry); return entry == null ? null : entry.location; } /** * Disposes this NavigationHistory and all entries. */ public void dispose() { disposeHistoryForTabs(); Iterator e = history.iterator(); while (e.hasNext()) { NavigationHistoryEntry entry = (NavigationHistoryEntry) e.next(); disposeEntry(entry); } } /** * Keeps a reference to the forward action to update its state * whenever needed. * <p> * (Called by NavigationHistoryAction) * </p> */ void setForwardAction(NavigationHistoryAction action) { forwardAction = action; updateActions(); } /** * Keeps a reference to the backward action to update its state * whenever needed. * <p> * (Called by NavigationHistoryAction) * </p> */ void setBackwardAction(NavigationHistoryAction action) { backwardAction = action; updateActions(); } /* * Returns the history entry indexed by <code>index</code> */ private NavigationHistoryEntry getEntry(int index) { if (0 <= index && index < history.size()) { return (NavigationHistoryEntry) history.get(index); } return null; } /* * Adds the specified entry to the history. */ private void add(NavigationHistoryEntry entry) { removeForwardEntries(); if (history.size() == CAPACITY) { NavigationHistoryEntry e = (NavigationHistoryEntry) history .remove(0); disposeEntry(e); } history.add(entry); activeEntry = history.size() - 1; } /* * Remove all entries after the active entry. */ private void removeForwardEntries() { int length = history.size(); for (int i = activeEntry + 1; i < length; i++) { NavigationHistoryEntry e = (NavigationHistoryEntry) history .remove(activeEntry + 1); disposeEntry(e); } } /* * Adds a location to the history. */ private void addEntry(IEditorPart part) { if (ignoreEntries > 0 || part == null) { return; } if (isPerTabHistoryEnabled()) { markLocationForTab(part); } INavigationLocation location = null; if (part instanceof INavigationLocationProvider) { location = ((INavigationLocationProvider) part) .createNavigationLocation(); } NavigationHistoryEntry current = getEntry(activeEntry); if (current != null && current.editorInfo.memento != null) { current.editorInfo.restoreEditor(); checkDuplicates(current.editorInfo); } NavigationHistoryEntry e = createEntry(page, part, location); if (current == null) { add(e); } else { if (e.mergeInto(current)) { disposeEntry(e); removeForwardEntries(); } else { add(e); } } printEntries("added entry"); //$NON-NLS-1$ updateActions(); } /* * Prints all the entries in the console. For debug only. */ private void printEntries(String label) { if (DEBUG) { System.out.println("+++++ " + label + "+++++ "); //$NON-NLS-1$ //$NON-NLS-2$ int size = history.size(); for (int i = 0; i < size; i++) { String append = activeEntry == i ? ">>" : ""; //$NON-NLS-1$ //$NON-NLS-2$ System.out.println(append + "Index: " + i + " " + history.get(i)); //$NON-NLS-1$ //$NON-NLS-2$ } } } /* * Returns true if the forward action can be performed otherwise returns false. * <p> * (Called by NavigationHistoryAction) * </p> */ /* package */boolean canForward() { if (isPerTabHistoryEnabled()) { return hasEntriesForTab(true); } return (0 <= activeEntry + 1) && (activeEntry + 1 < history.size()); } /* * Returns true if the backward action can be performed otherwise returns false. * <p> * (Called by NavigationHistoryAction) * </p> */ /* package */boolean canBackward() { if (isPerTabHistoryEnabled()) { return hasEntriesForTab(false); } return (0 <= activeEntry - 1) && (activeEntry - 1 < history.size()); } /* * Update the actions enable/disable and tooltip state. */ private void updateActions() { if (backwardAction != null) { backwardAction.update(); } if (forwardAction != null) { forwardAction.update(); } } /* * Restore the specified entry */ private void gotoEntry(NavigationHistoryEntry entry) { if (entry == null) { return; } try { ignoreEntries++; if (entry.editorInfo.memento != null) { entry.editorInfo.restoreEditor(); checkDuplicates(entry.editorInfo); } entry.restoreLocation(); updateActions(); printEntries("goto entry"); //$NON-NLS-1$ } finally { ignoreEntries--; } } /* * update the active entry */ private void updateEntry(NavigationHistoryEntry activeEntry) { if (activeEntry == null || activeEntry.location == null) { return; } activeEntry.location.update(); printEntries("updateEntry"); //$NON-NLS-1$ } /* * Perform the forward action by getting the next location and restoring * its context. * <p> * (Called by NavigationHistoryAction) * </p> */ void forward() { if (isPerTabHistoryEnabled()) { forwardForTab(); return; } if (canForward()) { shiftEntry(true); } } /* * Perform the backward action by getting the previous location and restoring * its context. * <p> * (Called by NavigationHistoryAction) * </p> */ void backward() { if (isPerTabHistoryEnabled()) { backwardForTab(); return; } if (canBackward()) { shiftEntry(false); } } /* * Shift the history back or forward */ private void shiftEntry(boolean forward) { updateEntry(getEntry(activeEntry)); if (forward) { activeEntry++; } else { activeEntry--; } NavigationHistoryEntry entry = getEntry(activeEntry); if (entry != null) { gotoEntry(entry); } } /* * Shift the history to the given entry. * <p> * (Called by NavigationHistoryAction) * </p> */ void shiftCurrentEntry(NavigationHistoryEntry entry, boolean forward) { if (isPerTabHistoryEnabled()) { gotoEntryForTab(entry, forward); return; } updateEntry(getEntry(activeEntry)); activeEntry = history.indexOf(entry); gotoEntry(entry); } /** * Save the state of this history into the memento. */ void saveState(IMemento memento) { NavigationHistoryEntry cEntry = getEntry(activeEntry); if (cEntry == null || !cEntry.editorInfo.isPersistable()) { return; } ArrayList editors = (ArrayList) this.editors.clone(); for (Iterator iter = editors.iterator(); iter.hasNext();) { NavigationHistoryEditorInfo info = (NavigationHistoryEditorInfo) iter .next(); if (!info.isPersistable()) { iter.remove(); } } IMemento editorsMem = memento .createChild(IWorkbenchConstants.TAG_EDITORS); for (Iterator iter = editors.iterator(); iter.hasNext();) { NavigationHistoryEditorInfo info = (NavigationHistoryEditorInfo) iter .next(); info.saveState(editorsMem .createChild(IWorkbenchConstants.TAG_EDITOR)); } ArrayList list = new ArrayList(history.size()); int size = history.size(); for (int i = 0; i < size; i++) { NavigationHistoryEntry entry = (NavigationHistoryEntry) history .get(i); if (entry.editorInfo.isPersistable()) { list.add(entry); } } size = list.size(); for (int i = 0; i < size; i++) { NavigationHistoryEntry entry = (NavigationHistoryEntry) list.get(i); IMemento childMem = memento .createChild(IWorkbenchConstants.TAG_ITEM); if (entry == cEntry) { childMem.putString(IWorkbenchConstants.TAG_ACTIVE, "true"); //$NON-NLS-1$ } entry.saveState(childMem, list); childMem.putInteger(IWorkbenchConstants.TAG_INDEX, editors .indexOf(entry.editorInfo)); } } /** * Restore the state of this history from the memento. */ void restoreState(IMemento memento) { IMemento editorsMem = memento.getChild(IWorkbenchConstants.TAG_EDITORS); IMemento items[] = memento.getChildren(IWorkbenchConstants.TAG_ITEM); if (items.length == 0 || editorsMem == null) { if (page.getActiveEditor() != null) { markLocation(page.getActiveEditor()); } return; } IMemento children[] = editorsMem .getChildren(IWorkbenchConstants.TAG_EDITOR); NavigationHistoryEditorInfo editorsInfo[] = new NavigationHistoryEditorInfo[children.length]; for (int i = 0; i < editorsInfo.length; i++) { editorsInfo[i] = new NavigationHistoryEditorInfo(children[i]); editors.add(editorsInfo[i]); } for (int i = 0; i < items.length; i++) { IMemento item = items[i]; int index = item.getInteger(IWorkbenchConstants.TAG_INDEX) .intValue(); NavigationHistoryEditorInfo info = editorsInfo[index]; info.refCount++; NavigationHistoryEntry entry = new NavigationHistoryEntry(info, page, null, null); history.add(entry); entry.restoreState(item); if (item.getString(IWorkbenchConstants.TAG_ACTIVE) != null) { activeEntry = i; } } final NavigationHistoryEntry entry = getEntry(activeEntry); if (entry != null && entry.editorInfo.editorInput != null) { if (page.getActiveEditor() == page .findEditor(entry.editorInfo.editorInput)) { StartupThreading.runWithoutExceptions(new StartupRunnable() { @Override public void runWithException() throws Throwable { gotoEntry(entry); }}); } } } public NavigationHistoryEntry createEntry(IWorkbenchPage page, IEditorPart part, INavigationLocation location) { String editorID = part.getSite().getId(); IEditorInput editorInput = part.getEditorInput(); NavigationHistoryEditorInfo info = null; for (Iterator iter = editors.iterator(); iter.hasNext();) { info = (NavigationHistoryEditorInfo) iter.next(); if (editorID.equals(info.editorID) && editorInput.equals(info.editorInput)) { info.refCount++; break; } info= null; } if (info == null) { info = new NavigationHistoryEditorInfo(part); info.refCount++; editors.add(info); } return new NavigationHistoryEntry(info, page, part, location); } public void disposeEntry(NavigationHistoryEntry entry) { if (entry.editorInfo == null) { return; } entry.editorInfo.refCount--; if (entry.editorInfo.refCount == 0) { editors.remove(entry.editorInfo); } entry.dispose(); } void checkDuplicates(NavigationHistoryEditorInfo info) { NavigationHistoryEditorInfo dup = null; if (info.editorInput == null) { return; } for (Iterator iter = editors.iterator(); iter.hasNext();) { dup = (NavigationHistoryEditorInfo) iter.next(); if (info != dup && info.editorID.equals(dup.editorID) && info.editorInput.equals(dup.editorInput)) { break; } dup= null; } if (dup == null) { return; } for (Iterator iter = history.iterator(); iter.hasNext();) { NavigationHistoryEntry entry = (NavigationHistoryEntry) iter.next(); if (entry.editorInfo == dup) { entry.editorInfo = info; info.refCount++; } } editors.remove(dup); } /*********************************************************/ /*** new per-tab history code ***/ /*********************************************************/ private static class PerTabHistory { LinkedList backwardEntries = new LinkedList(); NavigationHistoryEntry currentEntry = null; LinkedList forwardEntries = new LinkedList(); } private void setNewCurrentEntryForTab(PerTabHistory perTabHistory, NavigationHistoryEntry entry) { if (perTabHistory.currentEntry != null) { perTabHistory.backwardEntries.addFirst(perTabHistory.currentEntry); } perTabHistory.currentEntry = entry; removeEntriesForTab(perTabHistory.forwardEntries); } private Object getCookieForTab(IEditorPart part) { if (part != null) { IWorkbenchPartSite site = part.getSite(); if (site instanceof PartSite) { PartSite partSite = (PartSite) site; WorkbenchPartReference ref = (WorkbenchPartReference) partSite.getPartReference(); if (!ref.isDisposed()) { return partSite.getModel().getWidget(); } } } return null; } private void markLocationForTab(IEditorPart part) { if (part instanceof ErrorEditorPart) { updateActions(); return; } Object tabCookie = getCookieForTab(part); if (tabCookie != null) { INavigationLocation location = null; if (part instanceof INavigationLocationProvider) { location = ((INavigationLocationProvider) part) .createNavigationLocation(); } PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap .get(tabCookie); if (perTabHistory == null) { perTabHistory = new PerTabHistory(); perTabHistoryMap.put(tabCookie, perTabHistory); } NavigationHistoryEntry current = perTabHistory.currentEntry; if (current != null && current.editorInfo.memento != null) { current.editorInfo.restoreEditor(); checkDuplicates(current.editorInfo); } NavigationHistoryEntry entry = createEntry(page, part, location); if (current != null && entry.mergeInto(current)) { disposeEntry(entry); removeEntriesForTab(perTabHistory.forwardEntries); } else { setNewCurrentEntryForTab(perTabHistory, entry); } } updateActions(); } public void updateCookieForTab(Object oldCookie, Object newCookie) { if (newCookie.equals(oldCookie)) { return; } PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.remove(oldCookie); if (perTabHistory != null) { perTabHistoryMap.put(newCookie, perTabHistory); } } private void gotoEntryForTab(NavigationHistoryEntry target, boolean forward) { Object editorTabCookie = getCookieForTab(page.getActiveEditor()); if (editorTabCookie!=null) { PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie); if (perTabHistory != null) { LinkedList source = forward ? perTabHistory.forwardEntries : perTabHistory.backwardEntries; LinkedList destination = forward ? perTabHistory.backwardEntries : perTabHistory.forwardEntries; if (perTabHistory.currentEntry != null) { if (perTabHistory.currentEntry.location != null) { perTabHistory.currentEntry.location.update(); } destination.addFirst(perTabHistory.currentEntry); } NavigationHistoryEntry newCurrent = null; while (!source.isEmpty() && newCurrent==null) { NavigationHistoryEntry entry = (NavigationHistoryEntry) source .removeFirst(); if (entry.equals(target)) { newCurrent = entry; } else { destination.addFirst(entry); } } Assert.isTrue(newCurrent != null); perTabHistory.currentEntry = newCurrent; try { ignoreEntries++; if (newCurrent.editorInfo.memento != null) { newCurrent.editorInfo.restoreEditor(); checkDuplicates(newCurrent.editorInfo); } newCurrent.restoreLocation(); updateActions(); } finally { ignoreEntries--; } } } } private void forwardForTab() { Object editorTabCookie = getCookieForTab(page.getActiveEditor()); if (editorTabCookie!=null) { PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie); if (perTabHistory != null && !perTabHistory.forwardEntries.isEmpty()) { NavigationHistoryEntry newCurrent = (NavigationHistoryEntry) perTabHistory.forwardEntries .removeFirst(); if (perTabHistory.currentEntry != null) { final INavigationLocation location = perTabHistory.currentEntry.location; if (location!=null) { location.update(); } perTabHistory.backwardEntries.addFirst(perTabHistory.currentEntry); } perTabHistory.currentEntry = newCurrent; try { ignoreEntries++; if (newCurrent.editorInfo.memento != null) { newCurrent.editorInfo.restoreEditor(); checkDuplicates(newCurrent.editorInfo); } newCurrent.restoreLocation(); updateActions(); } finally { ignoreEntries--; } } } } private void backwardForTab() { Object editorTabCookie = getCookieForTab(page.getActiveEditor()); if (editorTabCookie!=null) { PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie); if (perTabHistory != null && !perTabHistory.backwardEntries.isEmpty()) { NavigationHistoryEntry newCurrent = (NavigationHistoryEntry) perTabHistory.backwardEntries .removeFirst(); if (perTabHistory.currentEntry != null) { perTabHistory.currentEntry.location.update(); perTabHistory.forwardEntries.addFirst(perTabHistory.currentEntry); } perTabHistory.currentEntry = newCurrent; try { ignoreEntries++; if (newCurrent.editorInfo.memento != null) { newCurrent.editorInfo.restoreEditor(); checkDuplicates(newCurrent.editorInfo); } newCurrent.restoreLocation(); updateActions(); } finally { ignoreEntries--; } } } } private boolean hasEntriesForTab(boolean forward) { Object editorTabCookie = getCookieForTab(page.getActiveEditor()); if (editorTabCookie!=null) { PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie); if (perTabHistory != null) { LinkedList entries = forward ? perTabHistory.forwardEntries : perTabHistory.backwardEntries; return !entries.isEmpty(); } } return false; } /** * Returns entries in restore order. * * @param forward <code>true</code> for forward and <code>false</code> for backward history * @return the navigation history entries */ private NavigationHistoryEntry[] getEntriesForTab(boolean forward) { Object editorTabCookie = getCookieForTab(page.getActiveEditor()); if (editorTabCookie != null) { PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap .get(editorTabCookie); if (perTabHistory != null) { LinkedList entries = forward ? perTabHistory.forwardEntries : perTabHistory.backwardEntries; return (NavigationHistoryEntry[]) entries .toArray(new NavigationHistoryEntry[entries.size()]); } } return new NavigationHistoryEntry[0]; } private void disposeHistoryForTabs() { Object[] keys = perTabHistoryMap.keySet().toArray(); for (Object key : keys) { disposeHistoryForTab(key); } } void disposeHistoryForTab(Object editorTabCookie) { PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.remove(editorTabCookie); if (perTabHistory != null) { if (perTabHistory.currentEntry != null) { disposeEntry(perTabHistory.currentEntry); perTabHistory.currentEntry = null; } removeEntriesForTab(perTabHistory.backwardEntries); removeEntriesForTab(perTabHistory.forwardEntries); } } private void removeEntriesForTab(LinkedList entries) { for (Iterator it = entries.iterator(); it.hasNext();) { NavigationHistoryEntry entry = (NavigationHistoryEntry) it.next(); disposeEntry(entry); it.remove(); } } public boolean updateActive(IEditorPart editor) { NavigationHistoryEntry e = getEntry(activeEntry); if (e == null) return false; // 1) check if editor ID matches IWorkbenchPartSite site = editor.getSite(); if (site == null) // might happen if site has not being initialized yet return false; String editorID = site.getId(); if (editorID == null) // should not happen for an editor return false; if (!editorID.equals(e.editorInfo.editorID)) return false; // 2) check that input matches IEditorInput input = editor.getEditorInput(); if (input == null) return false; if (!input.equals(e.editorInfo.editorInput)) return false; updateEntry(e); return true; } }